package com.srxz.personnelsystem.system.service.impl;

import com.srxz.personnelsystem.system.entity.DepartToPosition;
import com.srxz.personnelsystem.system.entity.Department;
import com.srxz.personnelsystem.system.entity.UserInfo;
import com.srxz.personnelsystem.system.mapper.converter.DepartmentMapper;
import com.srxz.personnelsystem.system.mapper.dto.DepartmentDTO;
import com.srxz.personnelsystem.system.mapper.dto.UserInfoDTO;
import com.srxz.personnelsystem.system.repository.DepartToPositionRepository;
import com.srxz.personnelsystem.system.repository.DepartmentRepository;
import com.srxz.personnelsystem.system.service.DepartmentService;
import com.srxz.personnelsystem.system.service.mapimpl.DepartmentMapperServiceImpl;
import com.srxz.personnelsystem.util.BackMessage;
import com.srxz.personnelsystem.util.PageParam;
import com.srxz.personnelsystem.util.TreeView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName: DepartmentServiceImpl
 * @author: wgchao
 * @createTime: 2019/1/23 4:56 PM
 * @Description: TODO
 */
@Service
@Transactional
public class DepartmentServiceImpl extends DepartmentMapperServiceImpl implements DepartmentService {
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private DepartToPositionRepository departToPositionRepository;

    @Override
    public BackMessage save(DepartmentDTO departmentDTO) {
        Department department = departmentMapper.entity(departmentDTO);
        department.setCreateTime(new Date());
        //TODO 设置创建人
        //TODO 获取部门编码

        department = departmentRepository.save(department);

        departmentDTO = departmentMapper.dto(department);
        extendCommon(departmentDTO);

        return BackMessage.success().putData(departmentDTO);
    }

    @Override
    public BackMessage update(DepartmentDTO departmentDTO) {
        Department department = departmentRepository.getOne(departmentDTO.getId());
        department.setName(departmentDTO.getName());

        department.setLastUpdateTime(new Date());
        //TODO 设置更新人


        department = departmentRepository.save(department);

        departmentDTO = departmentMapper.dto(department);
        extendCommon(departmentDTO);

        return BackMessage.success().putData(departmentDTO);
    }

    @Override
    public BackMessage delete(DepartmentDTO departmentDTO) {
        Department department = departmentRepository.getOne(departmentDTO.getId());
        department.setLastUpdateTime(new Date());
        department.setDeleteTime(new Date());
        //TODO 设置更新人\删除人


        department = departmentRepository.save(department);

        //删除下级部门
        deleteChilds(department);

        departmentDTO = departmentMapper.dto(department);
        extendCommon(departmentDTO);

        return BackMessage.success().putData(departmentDTO);
    }

    public void deleteChilds(Department department){
        List<Department> departments = departmentRepository.findAllByParentcodeAndDeleteTimeIsNull(department.getId());
        if(departments!=null && !departments.isEmpty()){
            for(Department department1:departments){
                department1.setLastUpdateTime(new Date());
                department1.setDeleteTime(new Date());
                //TODO 设置更新人\删除人
                department1 = departmentRepository.save(department1);
                deleteChilds(department1);
            }
        }
    }

    @Override
    public BackMessage search(String id) {
        Department department = departmentRepository.getOne(id);
        if(department != null){
            DepartmentDTO departmentDTO = departmentMapper.dto(department);
            extendCommon(departmentDTO);

            return BackMessage.success().putData(departmentDTO);
        }
        return BackMessage.success();
    }

    /**
     * 分页按条件查询部门信息列表
     * @param pageParam
     * @return
     */
    @Override
    public BackMessage searchToPage(PageParam pageParam) {
        Pageable pageable = PageRequest.of(pageParam.getOffset(), pageParam.getLimit());

        Specification<Department> dispatchSpecification = new Specification<Department>() {
            @Override
            public Predicate toPredicate(Root<Department> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //设置查询条件
                List<Predicate> list = new ArrayList<Predicate>();
                if (pageParam.getSearchCon() != null && !pageParam.getSearchCon().isEmpty()) {
                    for (Map.Entry<String, Object> km : pageParam.getSearchCon().entrySet()) {
                        String key = km.getKey();
                        Object val = km.getValue();
                        if ("dname".equals(key)) {//部门名称
                            if (val == null || val.toString().equals("")) {
                                continue;
                            }
                            Predicate p = criteriaBuilder.like(root.get("name").as(String.class), "%" + km.getValue().toString() + "%");
                            list.add(p);
                        }
                    }
                }
                //未删除
                Predicate p1 = criteriaBuilder.isNull(root.get("deleteTime").as(ZonedDateTime.class));
                list.add(p1);

                return criteriaBuilder.and(list.toArray(new Predicate[0]));
            }
        };

        //执行查询操作
        Page<Department> departments = departmentRepository.findAll(dispatchSpecification, pageable);
        List<DepartmentDTO> departmentDTOS = departments.getContent().stream().
                map(n -> {
                    DepartmentDTO departmentDTO = departmentMapper.dto(n);
                    extendCommon(departmentDTO);
                    return departmentDTO;
                }).collect(Collectors.toList());
        return BackMessage.success().putPageData(200, departmentDTOS);
    }

    /**
     * 查询机构下一级的部门列表
     * @param parentId 机构主键
     * @return
     */
    @Override
    public BackMessage searchByParent(String parentId) {

        //TODO 通过机构编号规则获取下级的部门列表
        return null;
    }

    @Override
    public BackMessage searchAllOfTree() {
        List<Department> departments = departmentRepository.findAllTop();
        List<DepartmentDTO> departmentDTOS = new ArrayList<>();
        if(departments != null){
            for(Department department:departments){
                DepartmentDTO departmentDTO = departmentMapper.dto(department);
                List<DepartmentDTO> childs = searchChilds(departmentDTO);
                if(childs!=null && !childs.isEmpty()){
                    departmentDTO.setChilds(childs);
                }
                departmentDTOS.add(departmentDTO);
            }
        }
        return BackMessage.success().putData(getTree(departmentDTOS));
    }

    @Override
    public BackMessage saveToPosition(DepartToPosition departToPosition) {
        departToPosition = departToPositionRepository.save(departToPosition);
        return BackMessage.success().putData(departToPosition);
    }

    @Override
    public BackMessage deleteToPosition(DepartToPosition departToPosition) {
        departToPositionRepository.deleteAllByDepartmentIdAndPositionId(departToPosition.getDepartmentId(), departToPosition.getPositionId());
        return BackMessage.success();
    }

    @Override
    public BackMessage deleteToPositionlist(List<DepartToPosition> departToPositions) {
        for(DepartToPosition departToPosition:departToPositions){
            departToPositionRepository.deleteAllByDepartmentIdAndPositionId(departToPosition.getDepartmentId(), departToPosition.getPositionId());
        }
        return BackMessage.success();
    }

    public List<DepartmentDTO> searchChilds(DepartmentDTO department){
        List<Department> departments = departmentRepository.findAllByParentcodeAndDeleteTimeIsNull(department.getId());
        List<DepartmentDTO> departmentDTOS = null;
        if(departments != null){
            departmentDTOS = departmentMapper.dto(departments);
            for(DepartmentDTO departmentDTO:departmentDTOS){
                departmentDTO.setChilds(searchChilds(departmentDTO));
            }
        }
        return departmentDTOS;
    }

    public List<TreeView> getTree(List<DepartmentDTO> departmentDTOS){
        List<TreeView> treeViews = new ArrayList<>();
        if(departmentDTOS!=null){
            for(DepartmentDTO departmentDTO:departmentDTOS){
                TreeView treeView = TreeView.getInstance(departmentDTO);
                if(departmentDTO.getChilds()!=null && !departmentDTO.getChilds().isEmpty()){
                    treeView.setNodes(getTree(departmentDTO.getChilds()));
                }
                treeViews.add(treeView);
            }
        }
        return treeViews;
    }

    public BackMessage searchAllCanUse(){
        List<Department> departments = departmentRepository.findAllByDeleteTimeIsNull();
        return BackMessage.success().putData(departmentMapper.dto(departments));
    }
}
